/* Yet Another Experimental Software Renderer
 *
 * Copyright (c) 2010 Pawel "Hery" Dziepak
 */

#ifndef VECTORS_H_
#define VECTORS_H_

#include "types.h"

namespace yaesr {

	struct vec2 {
		double x;
		double y;

		vec2() : x(0.0), y(0.0) {}
		vec2(double a, double b) : x(a), y(b) {}

		vec2 operator*(double val) {
			return vec2(x * val, y * val);
		}

		vec2 operator+(vec2 val) {
			return vec2(x + val.x, y + val.y);
		}
	};

	struct vec4 {
		double x;
		double y;
		double z;
		double w;

		vec4() : x(0.0), y(0.0), z(0.0), w(0.0) {}
		vec4(double a, double b, double c, double d) : x(a), y(b), z(c), w(d) {}

		vec4 operator*(double val) {
			return vec4(x * val, y * val, z * val, w * val);
		}

		vec4 operator/(double val) {
			return vec4(x / val, y / val, z / val, w / val);
		}

		vec4 operator+(vec4 val) {
			return vec4(x + val.x, y + val.y, z + val.z, w + val.w);
		}

		void operator+=(vec4 val) {
			x += val.x;
			y += val.y;
			z += val.z;
			w += val.w;
		}
	};

	struct color {
		double a;
		double r;
		double g;
		double b;

		color() : r(0.0), g(0.0), b(0.0), a(0.0) {}
		color(double _a, double _r, double _g, double _b) : a(_a), r(_r), g(_g), b(_b) { }
		color(double x) : a(x), r(x), g(x), b(x) { }

		color(vec4 vec) : a(vec.w), r(vec.x), g(vec.y), b(vec.z) {}
		operator vec4() const {
			return vec4(r, g, b, a);
		}

		color operator*(double val) const {
			return color(a * val, r * val, g * val, b * val);
		}

		color operator/(double val) const {
			return color(a / val, r / val, g / val, b / val);
		}

		color operator+(color val) const {
			return color(a + val.a, r + val.r, g + val.g, b + val.b);
		}

		u32 to_int32() const {
			u32 value = 0;
			value = int(255.0 * b);
			value |= int(255.0 * g) << 8;
			value |= int(255.0 * r) << 16;
			value |= int(255.0 * 0) << 24;

			return value;
		}

		static color from_int32(u32 value) {
			double alpha = ((value >> 24) & 0xff) / 255.0;
			double red = ((value >> 16) & 0xff) / 255.0;
			double green = ((value >> 8) & 0xff) / 255.0;
			double blue = (value & 0xff) / 255.0;

			return color(alpha, red, green, blue);
		}
	};
}

#endif